package com.betterjr.modules.temhandler.service;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.betterjr.common.service.BaseService;
import com.betterjr.common.utils.BTAssert;
import com.betterjr.common.utils.CacheUtils;
import com.betterjr.common.utils.Collections3;
import com.betterjr.common.utils.QueryTermBuilder;
import com.betterjr.modules.temhandler.dao.TemBusinRelationMapper;
import com.betterjr.modules.temhandler.data.TemHandlerConfigConstant;
import com.betterjr.modules.temhandler.data.TemRelationConstant;
import com.betterjr.modules.temhandler.entity.TemBusinRelation;
import com.betterjr.modules.temhandler.entity.TemData;

/**
 * 
 * @ClassName: TemBusinRelationService 
 * @Description: 配置关系service 
 * @author xuyp
 * @date 2018年1月9日 下午2:52:22 
 *
 */
@Service
public class TemBusinRelationService extends BaseService<TemBusinRelationMapper, TemBusinRelation>
        implements InitializingBean {

    /**
     * 
     * @Title: queryRelationByClassUrl 
     * @Description: 通过类的url和状态查询关系 
     * @param businTableType
     * @param anBusinStatus
     * @return 通过类的url和状态查询关系
     * @throws 
     * @author xuyp
     * @date 2017年12月21日 上午11:12:18
     */
    @SuppressWarnings("unchecked")
    public List<TemBusinRelation> queryRelationByClassUrl(String businTableType, String anBusinStatus) {

        BTAssert.isTrue(StringUtils.isNoneBlank(businTableType), "请绑定数据类型,操作失败");
        String redisKey = TemRelationConstant.TEMRELATION_STORE_REDIS_PRIMARTKEY_PREFIX + businTableType + "_"
                + anBusinStatus;
        try {
            // 从redis中获取关系数据
            Object object = CacheUtils.get(TemHandlerConfigConstant.CONFIGHANDLER_STOR_REDIS_CACHE_NAME, redisKey);
            if (object != null) {
                List listObject = JSONObject.parseObject(object.toString(), List.class);
                List<TemBusinRelation> relationList = new ArrayList<>(listObject.size());
                for (Object obj : listObject) {
                    if (obj != null) {

                        relationList.add(JSONObject.parseObject(obj.toString(), TemBusinRelation.class));
                    }
                }
                return relationList;
            }
        }
        catch (Exception e) {

            logger.info("从redis中获取配置信息出错  :" + businTableType + "   异常为：" + e.getMessage());
        }

        Map<String, Object> map = QueryTermBuilder.newInstance().put("classUrl", businTableType)
                .put("businStatus", TemRelationConstant.RELATION_BUSINSTATUS_EFFECITVE).build();

        if (StringUtils.isNoneBlank(anBusinStatus)) {
            if (anBusinStatus.contains(TemRelationConstant.SYSTEM_FILE_SPAREATOR)) {
                map.put("businStatus", anBusinStatus.split(TemRelationConstant.SYSTEM_FILE_SPAREATOR));
            } else {
                map.put("businStatus", anBusinStatus);
            }
        }

        List<TemBusinRelation> list = this.selectByProperty(map);

        try {
            // redis存放
            if (!Collections3.isEmpty(list)) {

                Object jsonData = JSONObject.toJSON(list);
                CacheUtils.put(TemHandlerConfigConstant.CONFIGHANDLER_STOR_REDIS_CACHE_NAME, redisKey, jsonData);
            }

        }
        catch (Exception e) {

            logger.info("从redis中写入配置信息出错  :" + businTableType + "   异常为：" + e.getMessage());
        }

        return list;
    }

    /**
     * 
     * @Title: packageQueryProperties 
     * @Description: 封装查询条件到temData中
     * @param anTemData 
     * @throws 
     * @author xuyp
     * @date 2017年12月27日 下午2:35:14
     */
    public void packageQueryProperties(TemData anTemData) {

        BTAssert.notNull(anTemData, "数据为空,操作失败");
        String businTableType = anTemData.getBusinTableType();
        BTAssert.isTrue(StringUtils.isNoneBlank(businTableType), "请绑定数据类型,操作失败");
        List<TemBusinRelation> relationList = queryRelationByClassUrl(businTableType,
                TemHandlerConfigConstant.CONFIGHANDLER_BUSINSTATUS_EFFECITVE);

        if (!Collections3.isEmpty(relationList)) {
            for (TemBusinRelation relation : relationList) {
                String propertiesValue = getPropertiesValue(relation.getBusinTableProperty(),
                        anTemData.getBusinTableData());
                if (StringUtils.isNoneBlank(propertiesValue)) {
                    try {
                        Field field = TemData.class.getDeclaredField(relation.getTemTableProperty());
                        field.setAccessible(true);
                        setFieldValue(field, propertiesValue, anTemData);
                    }
                    catch (Exception e) {
                        logger.info("封装" + anTemData.toString() + "值时发生异常" + e.getMessage());
                    }
                }
            }
        }

    }

    /**
     * 
     * @Title: convertQueryMap 
     * @Description: 前端查询条件后期封装（前端传递的是业务表中的数据）
     * @param anClassUrl  业务表类全路径
     * @param anQueryMap  前端传递的查询条件
     * @return 
     * @throws 
     * @author xuyp
     * @date 2017年12月28日 上午11:25:10
     */
    public Map<String, Object> convertQueryMap(String anClassUrl, Map<String, Object> anQueryMap) {

        if (StringUtils.isNoneBlank(anClassUrl)) {
            List<TemBusinRelation> list = queryRelationByClassUrl(anClassUrl,
                    TemRelationConstant.RELATION_BUSINSTATUS_EFFECITVE);
            if (!Collections3.isEmpty(list)) {

                Map<String, Object> map = new HashMap<>(list.size());
                for (TemBusinRelation temBusinRelation : list) {
                    convertPropertiesValueToMap(map, temBusinRelation, anQueryMap);
                }

                return map;
            }
        }

        return new HashMap<>();
    }

    /**
     * 
     * @Title: convertPropertiesValueToMap 
     * @Description: 转换每个属性的值存放到目标map中去 
     * @param map  目标存储map
     * @param temBusinRelation  对应关系对象
     * @param anQueryMap 前端传递的值
     * @throws 
     * @author xuyp
     * @date 2017年12月28日 上午11:32:29
     */
    private void convertPropertiesValueToMap(Map<String, Object> map, TemBusinRelation temBusinRelation,
            Map<String, Object> anQueryMap) {

        if (!Collections3.isEmpty(anQueryMap)) {
            for (String key : anQueryMap.keySet()) {
                if (key.contains(temBusinRelation.getBusinTableProperty())) {
                    Object value = anQueryMap.get(key);
                    String temKey = key.replaceAll(temBusinRelation.getBusinTableProperty(),
                            temBusinRelation.getTemTableProperty());
                    map.put(temKey, value);
                }

            }
        }

    }

    /**
     * 
     * @Title: removeRedisTemRelation 
     * @Description: 批量移除redis中临时关系表数据
     * @param businTableType 类全路径
     * @throws 
     * @author xuyp
     * @date 2017年12月27日 下午6:11:11
     */
    private void removeRedisTemRelation(String businTableType, String anBusinStatus) {

        if (StringUtils.isNoneBlank(businTableType) && StringUtils.isNoneBlank(anBusinStatus)) {
            String redisKey = TemRelationConstant.TEMRELATION_STORE_REDIS_PRIMARTKEY_PREFIX + businTableType + "_"
                    + anBusinStatus;

            CacheUtils.remove(TemHandlerConfigConstant.CONFIGHANDLER_STOR_REDIS_CACHE_NAME, redisKey);
        } else if (StringUtils.isNoneBlank(businTableType)) {
            String redisKey = TemRelationConstant.TEMRELATION_STORE_REDIS_PRIMARTKEY_PREFIX + businTableType;

            CacheUtils.removeByPrefix(TemHandlerConfigConstant.CONFIGHANDLER_STOR_REDIS_CACHE_NAME, redisKey);

        } else {
            String redisKey = TemRelationConstant.TEMRELATION_STORE_REDIS_PRIMARTKEY_PREFIX;

            CacheUtils.removeByPrefix(TemHandlerConfigConstant.CONFIGHANDLER_STOR_REDIS_CACHE_NAME, redisKey);
        }

    }

    /**
     * 
     * @Title: getPropertiesValue 
     * @Description: 查询string对象里面的值
     * @param string
     * @param businTableData
     * @return 查询string对象里面的值
     * @throws 
     * @author xuyp
     * @date 2017年12月25日 上午9:48:50
     */
    private String getPropertiesValue(String properties, String jsonData) {

        if (StringUtils.isNoneBlank(properties) && StringUtils.isNoneBlank(jsonData)) {
            JSONObject parseObject = JSONObject.parseObject(jsonData);
            return parseObject.getString(properties);
        }
        return null;
    }

    /**
     * 
     * @Title: setFieldValue 
     * @Description: 根据参数类型设置field的值
     * @param field
     * @param value
     * @param object 根据参数类型设置field的值
     * @throws 
     * @author xuyp
     * @date 2017年12月26日 下午3:47:52
     */
    private void setFieldValue(Field field, Object value, Object object) {

        if (field != null && value != null && object != null) {

            // 参数类型
            Class<?> type = field.getType();
            value = objectValueJavaTypeConvert(value, type);

            try {
                field.set(object, value);
            }
            catch (Exception e) {

                logger.info("设置参数出错" + e.getMessage());
                BTAssert.notNull(null, e.getMessage());
            }

        }

    }

    /**
     * 
     * @Title: objectValueJavaTypeConvert 
     * @Description: 值java类型转换
     * @param value
     * @param type
     * @return 值java类型转换
     * @throws 
     * @author xuyp
     * @date 2017年12月26日 下午4:22:13
     */
    private Object objectValueJavaTypeConvert(Object value, Class<?> type) {
        try {
            if (type != null) {
                String name = type.getName().toUpperCase();
                if (name.contains("STRING")) {
                    value = value.toString();
                } else if (name.contains("LONG")) {
                    value = Long.parseLong(value.toString());
                } else if (name.contains("BOOLEAN")) {
                    value = Boolean.parseBoolean(value.toString());
                } else if (name.contains("INT")) {
                    value = Integer.parseInt(value.toString());
                } else if (name.contains("DOUBLE")) {
                    value = Double.parseDouble(value.toString());
                } else if (name.contains("FLOAT")) {
                    value = Float.parseFloat(value.toString());
                }
            }
        }
        catch (Exception e) {
            logger.info("转换数据类型出错" + e.getMessage());
            BTAssert.notNull(null, e.getMessage());
        }
        return value;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        removeRedisTemRelation("", "");

    }

}
